package com.quectel.business.pay.handler;

import cn.hutool.core.bean.BeanUtil;
import com.google.common.base.Preconditions;
import com.quectel.business.pay.handler.model.CreateBusinessResp;
import com.quectel.business.pay.vo.CreateOrderRequest;
import com.quectel.constant.core.parkingcard.ParkingCardMemberConstants;
import com.quectel.constant.core.parkingcard.ParkingCardOrderConstants;
import com.quectel.core.module.car.dto.CarDto;
import com.quectel.core.module.car.service.CarService;
import com.quectel.core.module.household.dto.HouseholdDto;
import com.quectel.core.module.household.service.HouseholdService;
import com.quectel.core.module.mobileuser.dto.MobileUserCarDto;
import com.quectel.core.module.mobileuser.service.MobileUserCarService;
import com.quectel.core.module.mobileuser.service.MobileUserService;
import com.quectel.core.module.parkingcard.dto.ParkingCardDto;
import com.quectel.core.module.parkingcard.dto.ParkingCardMemberDto;
import com.quectel.core.module.parkingcard.dto.ParkingCardOrderDto;
import com.quectel.core.module.parkingcard.service.ParkingCardMemberService;
import com.quectel.core.module.parkingcard.service.ParkingCardOrderService;
import com.quectel.core.module.parkingcard.service.ParkingCardService;
import com.quectel.pay.module.order.dto.PayOrderDto;
import com.quectel.pay.module.order.dto.PayOrderRefundDto;
import com.quectel.util.common.CopyUtils;
import com.quectel.util.common.JacksonUtils;
import com.quectel.util.common.Response;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * 停车月卡缴费
 */
@Slf4j
@Component
public class ParkingCardFeePayHandler implements BasePayHandler{

    /**
     * 停车月卡购买参数
     */
    @Data
    public static class BuyCardParamsCls{
        private  Long cardId;
        private  String license;
        private  Byte licenseColor;
    }

    @DubboReference
    private ParkingCardService parkingCardService;
    @DubboReference
    private ParkingCardOrderService parkingCardOrderService;
    @DubboReference
    private CarService carService;
    @DubboReference
    private MobileUserCarService mobileUserCarService;
    @DubboReference
    private MobileUserService mobileUserService;
    @DubboReference
    private HouseholdService householdService;
    @DubboReference
    private ParkingCardMemberService parkingCardMemberService;

    @Override
    public Response<CreateBusinessResp> createBusinessOrder(CreateOrderRequest req) {
        BuyCardParamsCls buyCardParamsCls = BeanUtil.toBean(req.getOtherBusinessParams(), BuyCardParamsCls.class);
        ParkingCardDto parkingCardDto = parkingCardService.selectCacheById(buyCardParamsCls.getCardId());
        if (Objects.isNull(parkingCardDto)) {
            return Response.error("月卡配置不存在");
        }

        ParkingCardMemberDto parkingCardMemberDto = parkingCardMemberService.selectOneMember(parkingCardDto.getVillageId()
                , buyCardParamsCls.getLicense(), buyCardParamsCls.getLicenseColor());
        if (Objects.nonNull(parkingCardMemberDto)
                && ParkingCardMemberConstants.MemberIsFreezeEnum.IS_FREEZE.getFreezeStatus().equals(parkingCardMemberDto.getIsFreeze())) {
            return Response.error("会员被冻结");
        }

        Boolean isRegistCar = Boolean.TRUE;
        CarDto carDto = carService.selectOneByCache(parkingCardDto.getVillageId()
                , buyCardParamsCls.getLicense(), buyCardParamsCls.getLicenseColor());
        if (Objects.isNull(carDto)) {
            // 用户车辆未认证，车辆可能来源其他小区的注册车辆，可能来源mobileUser车辆
            isRegistCar = Boolean.FALSE;

            List<CarDto> carDtos = carService.selectByMobile(req.getMobile());
            carDto = carDtos.parallelStream().filter(o -> o.getLicense().equals(buyCardParamsCls.getLicense())
                    && o.getLicenseColor().equals(buyCardParamsCls.getLicenseColor())).findFirst().orElse(null);

            if (Objects.isNull(carDto)) {
                // 如果车辆还是没找到，只能说明来源于mobileUser添加的未认证车辆
                List<MobileUserCarDto> mobileUserCarDtoList = mobileUserCarService.selectByMobile(req.getMobile());
                MobileUserCarDto mobileUserCarDto = mobileUserCarDtoList.parallelStream().filter(o -> o.getLicense().equals(buyCardParamsCls.getLicense())
                        && o.getLicenseColor().equals(buyCardParamsCls.getLicenseColor())).findFirst().orElse(null);
                if (Objects.nonNull(mobileUserCarDto)) {
                    carDto = CopyUtils.copyObj(mobileUserCarDto, CarDto.class);
                }
            }
        }else{
            // 认证车辆不为空，查看是否为当前住户的车辆
            if (!carDto.getOwnerMobile().equals(req.getMobile())) {
                return Response.error("该车辆已被其他人认证，请确认车牌信息");
            }
        }

        if (Objects.isNull(carDto)) {
            return Response.error("车辆不存在");
        }

        HouseholdDto householdDto = householdService.selectByVillageIdAndMobile(parkingCardDto.getVillageId(), req.getMobile());
        if (Objects.isNull(householdDto)) {
            return Response.error("住户未认证");
        }

        final Date currentDate = new Date();

        ParkingCardOrderDto orderReq = new ParkingCardOrderDto();
        orderReq.setTenantId(parkingCardDto.getTenantId());
        orderReq.setVillageId(parkingCardDto.getVillageId());
        orderReq.setSourceType(ParkingCardOrderConstants.OrderSourceTypeEnum.HOUSEHOLD.getSourceType());
        orderReq.setSourceId(householdDto.getId());
        orderReq.setIsRegistCar(Boolean.TRUE.equals(isRegistCar) ? ParkingCardOrderConstants.OrderIsRegistCarEnum.IS_REGIST.getRegistStatus()
                : ParkingCardOrderConstants.OrderIsRegistCarEnum.NO_REGIST.getRegistStatus());
        orderReq.setHouseholdId(householdDto.getId());
        orderReq.setCarId(carDto.getId());
        orderReq.setLicense(carDto.getLicense());
        orderReq.setLicenseColor(carDto.getLicenseColor());
        orderReq.setAuditStatus(ParkingCardOrderConstants.OrderAuditStatusEnum.NO_AUDIT.getAuditStatus());
        orderReq.setCardId(parkingCardDto.getId());
        orderReq.setCardType(parkingCardDto.getType());
        orderReq.setCardJson(JacksonUtils.toJsonString(parkingCardDto));
        orderReq.setPayType(req.getPayType());
        orderReq.setPayStatus(ParkingCardOrderConstants.OrderPayStatusEnum.NO_PAY.getPayStatus());
        orderReq.setPayAmount(parkingCardDto.getDiscountPrice());
        orderReq.setInvoiceStatus(ParkingCardOrderConstants.OrderInvoiceStatusEnum.NO_INVOICE.getInvoiceStatus());
        orderReq.setTransactTime(currentDate);
        Long orderId = parkingCardOrderService.save(orderReq);
        if (Objects.nonNull(orderId)) {
            CreateBusinessResp createBusinessResp = new CreateBusinessResp();
            createBusinessResp.setTenantId(parkingCardDto.getTenantId());
            createBusinessResp.setVillageId(parkingCardDto.getVillageId());
            createBusinessResp.setBusinessId(orderId);
            createBusinessResp.setProductName(parkingCardDto.getName());
            createBusinessResp.setOriginalPrice(parkingCardDto.getPrice());
            createBusinessResp.setSpecialPrice(parkingCardDto.getDiscountPrice());
            createBusinessResp.setTtl(null);
            return Response.<CreateBusinessResp>ok().wrap(createBusinessResp);
        }
        return Response.error("办卡申请失败");
    }

    @Override
    public Response<Object> createOrderSuccessNotify(PayOrderDto notifyOrder) {
        ParkingCardOrderDto parkingCardOrderDto = parkingCardOrderService.selectCacheById(notifyOrder.getBusinessId());
        Preconditions.checkNotNull(parkingCardOrderDto);

        ParkingCardOrderDto newlyDto = new ParkingCardOrderDto();
        newlyDto.setId(parkingCardOrderDto.getId());
        newlyDto.setOrderId(notifyOrder.getId());
        newlyDto.setOrderNo(notifyOrder.getOutTradeNo());
        parkingCardOrderService.updateById(newlyDto);
        return Response.ok();
    }

    @Override
    public Response<Object> createOrderFailedNotify(CreateOrderRequest req) {
        return null;
    }

    @Override
    public Response<Object> cancelOrder(PayOrderDto cancelOrder) {
        return Response.ok();
    }

    @Override
    public Response<Object> paySuccessNotify(PayOrderDto order) {
        ParkingCardOrderDto parkingCardOrderDto = parkingCardOrderService.selectCacheById(order.getBusinessId());
        Preconditions.checkNotNull(parkingCardOrderDto);

        ParkingCardOrderDto newlyDto = new ParkingCardOrderDto();
        newlyDto.setId(parkingCardOrderDto.getId());
//        newlyDto.setOrderId(order.getId());
        newlyDto.setPayStatus(ParkingCardOrderConstants.OrderPayStatusEnum.PAY_SUCCESS.getPayStatus());
        newlyDto.setOrderNo(order.getOutTradeNo());
        parkingCardOrderService.updateById(newlyDto);
        return Response.ok();
    }

    @Override
    public Response<Object> refundPreCheck(PayOrderDto payOrderDto, BigDecimal refundAmount) {
        // 后续有规则性检查需要，状态性无需检查
        return Response.ok();
    }

    @Override
    public Response<Object> refundSuccessNotify(PayOrderRefundDto refundOrder) {
        PayOrderDto payOrderDto = refundOrder.getPayOrderDto();
        ParkingCardOrderDto parkingCardOrderDto = parkingCardOrderService.selectCacheById(payOrderDto.getBusinessId());
        Preconditions.checkNotNull(parkingCardOrderDto);

        ParkingCardOrderDto newlyDto = new ParkingCardOrderDto();
        newlyDto.setId(parkingCardOrderDto.getId());
        newlyDto.setAuditStatus(ParkingCardOrderConstants.OrderAuditStatusEnum.IS_REJECT.getAuditStatus());
        newlyDto.setPayStatus(ParkingCardOrderConstants.OrderPayStatusEnum.IS_REFUND.getPayStatus());
        newlyDto.setRefundAmount(refundOrder.getRefundAmount());
        newlyDto.setRefundTime(new Date());
        parkingCardOrderService.updateById(newlyDto);
        return Response.ok();
    }
}
